﻿  //===============================EdgeDetectionAlgorithm.cs===============================\\
 //===========================THis Algorithm is not made by us!!!===========================\\
//=Source: codeproject.com/Articles/37299/Implementation-of-Laplacian-of-Gaussion-Edge-Detec=\\



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Collections;

namespace Team2_Vision
{
    class EdgeDetection : VisionAlgorithm
    {
        public EdgeDetection(String name) : base(name) { }
        public override System.Drawing.Bitmap DoAlgorithm(System.Drawing.Bitmap SrcImage, int matrix)
        {
            double[,] MASK = new double[12, 12] {
								{-0.000699762,	-0.000817119,	-0.000899703,	-0.000929447,	-0.000917118,	-0.000896245,	-0.000896245,	-0.000917118,	-0.000929447,	-0.000899703,	-0.000817119,	-0.000699762},
								{-0.000817119,	-0.000914231,	-0.000917118,	-0.000813449,	-0.000655442,	-0.000538547,	-0.000538547,	-0.000655442,	-0.000813449,	-0.000917118,	-0.000914231,	-0.000817119},
								{-0.000899703,	-0.000917118,	-0.000745635,	-0.000389918,	0.0000268,	0.000309618,	0.000309618,	0.0000268,	-0.000389918,	-0.000745635,	-0.000917118,	-0.000899703},
								{-0.000929447,	-0.000813449,	-0.000389918,	0.000309618,	0.001069552,	0.00156934,	0.00156934,	0.001069552,	0.000309618,	-0.000389918,	-0.000813449,	-0.000929447},
								{-0.000917118,	-0.000655442,	0.0000268,	0.001069552,	0.002167033,	0.002878738,	0.002878738,	0.002167033,	0.001069552,	0.0000268,	-0.000655442,	-0.000917118},
								{-0.000896245,	-0.000538547,	0.000309618,	0.00156934,	0.002878738,	0.003722998,	0.003722998,	0.002878738,	0.00156934,	0.000309618,	-0.000538547,	-0.000896245},
								{-0.000896245,	-0.000538547,	0.000309618,	0.00156934,	0.002878738,	0.003722998,	0.003722998,	0.002878738,	0.00156934,	0.000309618,	-0.000538547,	-0.000896245},
								{-0.000917118,	-0.000655442,	0.0000268,	0.001069552,	0.002167033,	0.002878738,	0.002878738,	0.002167033,	0.001069552,	0.0000268,	-0.000655442,	-0.000917118},
								{-0.000929447,	-0.000813449,	-0.000389918,	0.000309618,	0.001069552,	0.00156934,	0.00156934,	0.001069552,	0.000309618,	-0.000389918,	-0.000813449,	-0.000929447},
								{-0.000899703,	-0.000917118,	-0.000745635,	-0.000389918,	0.0000268,	0.000309618,	0.000309618,	0.0000268,	-0.000389918,	-0.000745635,	-0.000917118,	-0.000899703},
								{-0.000817119,	-0.000914231,	-0.000917118,	-0.000813449,	-0.000655442,	-0.000538547,	-0.000538547,	-0.000655442,	-0.000813449,	-0.000917118,	-0.000914231,	-0.000817119},
								{-0.000699762,	-0.000817119,	-0.000899703,	-0.000929447,	-0.000917118,	-0.000896245,	-0.000896245,	-0.000917118,	-0.000929447,	-0.000899703,	-0.000817119,	-0.000699762}
							};

            double nTemp = 0.0;

            
            double c = 0;

            int mdl, size;
            size = 12;
            mdl = size / 2;

            double min, max;
            min = max = 0.0;

            double sum = 0.0;
            double mean;
            double d = 0.0;
            double s = 0.0;
            int n = 0;

            Bitmap bitmap = new Bitmap(SrcImage.Width + mdl, SrcImage.Height + mdl);
            int l, k;

            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData srcData = SrcImage.LockBits(new Rectangle(0, 0, SrcImage.Width, SrcImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            unsafe
            {
                int offset = 3;

                for (int colm = 0; colm < srcData.Height - size; colm++)
                {
                    byte* ptr = (byte*)srcData.Scan0 + (colm * srcData.Stride);
                    byte* bitmapPtr = (byte*)bitmapData.Scan0 + (colm * bitmapData.Stride);

                    for (int row = 0; row < srcData.Width - size; row++)
                    {
                        nTemp = 0.0;
                        min = double.MaxValue;
                        max = double.MinValue;

                        for (k = 0; k < size; k++)
                        {
                            for (l = 0; l < size; l++)
                            {
                                byte* tempPtr = (byte*)srcData.Scan0 + ((colm + l) * srcData.Stride);
                                c = (tempPtr[((row + k) * offset)] + tempPtr[((row + k) * offset) + 1] + tempPtr[((row + k) * offset) + 2]) / 3;
                                nTemp += (double)c * MASK[k, l];
                            }
                        }
                        sum += nTemp;
                        n++;
                    }
                }
                mean = ((double)sum / n);
                d = 0.0;

                for (int i = 0; i < srcData.Height - size; i++)
                {
                    byte* ptr = (byte*)srcData.Scan0 + (i * srcData.Stride);
                    byte* tptr = (byte*)bitmapData.Scan0 + (i * bitmapData.Stride);

                    for (int j = 0; j < srcData.Width - size; j++)
                    {
                        nTemp = 0.0;
                        min = double.MaxValue;
                        max = double.MinValue;
                        for (k = 0; k < size; k++)
                        {
                            for (l = 0; l < size; l++)
                            {
                                byte* tempPtr = (byte*)srcData.Scan0 + ((i + l) * srcData.Stride);
                                c = (tempPtr[((j + k) * offset)] + tempPtr[((j + k) * offset) + 1] + tempPtr[((j + k) * offset) + 2]) / 3;
                                nTemp += (double)c * MASK[k, l];
                            }
                        }
                        s = (mean - nTemp);
                        d += (s * s);
                    }
                }

                d = d / (n - 1);
                d = Math.Sqrt(d);
                d = d * 2;

                for (int colm = mdl; colm < srcData.Height - mdl; colm++)
                {
                    byte* ptr = (byte*)srcData.Scan0 + (colm * srcData.Stride);
                    byte* bitmapPtr = (byte*)bitmapData.Scan0 + (colm * bitmapData.Stride);

                    for (int row = mdl; row < srcData.Width - mdl; row++)
                    {
                        nTemp = 0.0;

                        min = double.MaxValue;
                        max = double.MinValue;

                        for (k = (mdl * -1); k < mdl; k++)
                        {
                            for (l = (mdl * -1); l < mdl; l++)
                            {
                                byte* tempPtr = (byte*)srcData.Scan0 + ((colm + l) * srcData.Stride);
                                c = (tempPtr[((row + k) * offset)] + tempPtr[((row + k) * offset) + 1] + tempPtr[((row + k) * offset) + 2]) / 3;
                                nTemp += (double)c * MASK[mdl + k, mdl + l];
                            }
                        }

                        if (nTemp > d)
                        {
                            bitmapPtr[row * offset] = bitmapPtr[row * offset + 1] = bitmapPtr[row * offset + 2] = 255;
                        }
                        else
                            bitmapPtr[row * offset] = bitmapPtr[row * offset + 1] = bitmapPtr[row * offset + 2] = 0;
                    }
                }
            }

            bitmap.UnlockBits(bitmapData);
            SrcImage.UnlockBits(srcData);
            return bitmap;
        }
    }

}